<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>OpenMesh: Using standard properties</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="logo_align.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="rwth_vci_rgb.jpg"/></td>
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">OpenMesh
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('a04340.html','');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">Using standard properties </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>This example shows:</p>
<ul>
<li>How to add and remove a standard property,</li>
<li>How to get and set the value of a standard property.</li>
</ul>
<p>As we already have seen, we can bind additional data to the mesh entities by means of properties. OpenMesh provides a set of so-called standard properties. Unlike the custom properties these have some special features and a different interface, which are the matter in this tutorial.</p>
<p>The following table lists all available standard properties and the suitable entity for which it can be used.</p>
<table class="doxtable">
<tr>
<td>&#160; </td><td>Vertex </td><td>Face </td><td>Edge </td><td>Halfedge  </td></tr>
<tr>
<td>Color </td><td>X </td><td>X </td><td>X </td><td>&#160;  </td></tr>
<tr>
<td>Normal </td><td>X </td><td>X </td><td>&#160; </td><td>X  </td></tr>
<tr>
<td>Position <sup> (*) </sup>  </td><td>X </td><td>&#160; </td><td>&#160; </td><td>&#160;  </td></tr>
<tr>
<td>Status </td><td>X </td><td>X </td><td>X </td><td>X  </td></tr>
<tr>
<td>TexCoord </td><td>X </td><td>&#160; </td><td>&#160; </td><td>X  </td></tr>
</table>
<p>To add a standard property to an entity simply use the appropriate request method, e.g. <code>request_face_normals()</code>. The only exception is the position <sup>(*)</sup>. It cannot be added because it is permanently available, hence it cannot be removed as well.</p>
<p>In this example we</p><ol type="1">
<li>add vertex normals to a mesh object</li>
<li>load a file</li>
<li>check if the file provides vertex normals and calculate them if not</li>
<li>move every vertex one unit length along its normal direction</li>
<li>print the resulting positions to std::cout</li>
</ol>
<p>Let's start with adding vertex normals to the mesh:</p>
 <div class="fragment"><div class="line">  mesh.request_vertex_normals();</div></div><!-- fragment --></p>
<p>In a similar manner we can request the other standard properties. For example the face normals:</p>
<p><div class="fragment"><div class="line">    mesh.request_face_normals();</div></div><!-- fragment --></p>
<p>We need them to calculate the vertex normals with <code>update_normals()</code>, if the file didn't provide any.</p>
<p>But we can do more with standard properties. We can verify if the mesh has already the property vertex normals</p>
 <div class="fragment"><div class="line">  <span class="keywordflow">if</span> (!mesh.has_vertex_normals())</div><div class="line">  {</div><div class="line">    std::cerr &lt;&lt; <span class="stringliteral">&quot;ERROR: Standard vertex property &#39;Normals&#39; not available!\n&quot;</span>;</div><div class="line">    <span class="keywordflow">return</span> 1;</div><div class="line">  }</div></div><!-- fragment --></p>
<p>And after usage we remove them again</p>
<p><div class="fragment"><div class="line">  mesh.release_vertex_normals();</div></div><!-- fragment --></p>
<p>But, what happens if for example the vertex status property has been requested twice? Then the first release does nothing, but the second one will remove it. The standard properties have a reference counter, which is incremented by one for each request and decremented by one for each release. If the counter reaches 0 the property will be removed from memory.</p>
<p>As we have seen in the table above, we have 9 dynamically requestable properties. The request functions as defined in <a class="el" href="a01877.html" title="This class describes the minimum interface a mesh kernel has to implement (because the resulting mesh...">OpenMesh::Concepts::KernelT</a> are:</p>
<ul>
<li>
request_edge_status() </li>
<li>
request_edge_colors() </li>
<li>
request_face_colors() </li>
<li>
request_face_normals() </li>
<li>
request_face_status() </li>
<li>
request_face_texture_index() </li>
<li>
request_halfedge_status() </li>
<li>
request_halfedge_normals() </li>
<li>
request_halfedge_texcoords1D() </li>
<li>
request_halfedge_texcoords2D() </li>
<li>
request_halfedge_texcoords3D() </li>
<li>
request_vertex_colors() </li>
<li>
request_vertex_normals() </li>
<li>
request_vertex_status() </li>
<li>
request_vertex_texcoords1D() </li>
<li>
request_vertex_texcoords2D() </li>
<li>
request_vertex_texcoords3D() </li>
</ul>
<p>Added properties can be released by the following functions:</p>
<ul>
<li>
release_edge_status() </li>
<li>
release_edge_colors() </li>
<li>
release_face_colors() </li>
<li>
release_face_normals() </li>
<li>
release_face_status() </li>
<li>
release_face_texture_index() </li>
<li>
release_halfedge_status() </li>
<li>
release_halfedge_normals() </li>
<li>
release_halfedge_texcoords1D() </li>
<li>
release_halfedge_texcoords2D() </li>
<li>
release_halfedge_texcoords3D() </li>
<li>
release_vertex_colors() </li>
<li>
release_vertex_normals() </li>
<li>
release_vertex_status() </li>
<li>
release_vertex_texcoords1D() </li>
<li>
release_vertex_texcoords2D() </li>
<li>
release_vertex_texcoords3D() </li>
</ul>
<p>A property's existance can be tested with</p>
<ul>
<li>
has_edge_status() </li>
<li>
has_edge_colors() </li>
<li>
has_face_colors() </li>
<li>
has_face_normals() </li>
<li>
has_face_status() </li>
<li>
has_face_texture_index() </li>
<li>
has_halfedge_status() </li>
<li>
has_halfedge_normals() </li>
<li>
has_halfedge_texcoords1D() </li>
<li>
has_halfedge_texcoords2D() </li>
<li>
has_halfedge_texcoords3D() </li>
<li>
has_vertex_colors() </li>
<li>
has_vertex_normals() </li>
<li>
has_vertex_status() </li>
<li>
has_vertex_texcoords1D() </li>
<li>
has_vertex_texcoords2D() </li>
<li>
has_vertex_texcoords3D() </li>
</ul>
<p>which return true if a property has been requested before and is available.</p>
<p>The status property is used for marking geometry elements i.e. as selected or deleted. See <a class="el" href="a04343.html">Deleting geometry elements</a> for further information.</p>
<p>Now we know how to add and remove standard properties, but how do we access them? Again we need the mesh object. Unlike the custom properties, where we accessed one with the mesh member function <code>property()</code>, for each standard property the mesh provides a get and a set method. We have used one pair of get/set methods already in the previous three tutorials, where we computed a new location for the vertex position. Here we move all vertices a unit length along their normal direction:</p>
 <div class="fragment"><div class="line">  <span class="keywordflow">for</span> (MyMesh::VertexIter v_it = mesh.vertices_begin();</div><div class="line">       v_it != mesh.vertices_end(); ++v_it)</div><div class="line">  {</div><div class="line">    mesh.set_point( *v_it, mesh.point(*v_it)+mesh.normal(*v_it) );</div><div class="line">  }</div></div><!-- fragment --></p>
<p>The get-methods take an entity handle and return the value of the desired property, and the set-methods require an additional parameter to pass the new value to the property. According to the table not every pair of get/set-methods apply to every entity. For example a face has normally no texture coordinates, hence a call to <code>mesh.texcoord2D( _face_handle )</code> will result in an error when compiling the code.</p>
<p>Since we know how to add/remove/access standard properties, one further question remains. What data types do they have? And are there more hidden secrets? The next tutorial (<a class="el" href="a04341.html">Using mesh attributes and traits</a>) will give the answer.</p>
<p>The complete source looks like this:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div><div class="line"><span class="comment">// --------------------</span></div><div class="line"><span class="preprocessor">#include &lt;OpenMesh/Core/IO/MeshIO.hh&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh&gt;</span></div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">typedef</span> <a class="code" href="a02377.html">OpenMesh::TriMesh_ArrayKernelT&lt;&gt;</a>  MyMesh;</div><div class="line"></div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> **argv)</div><div class="line">{</div><div class="line">  MyMesh  mesh;</div><div class="line"></div><div class="line">  <span class="keywordflow">if</span> (argc!=2)</div><div class="line">  {</div><div class="line">    std::cerr &lt;&lt; <span class="stringliteral">&quot;Usage: &quot;</span> &lt;&lt; argv[0] &lt;&lt; <span class="stringliteral">&quot; &lt;input&gt;\n&quot;</span>;</div><div class="line">    <span class="keywordflow">return</span> 1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// request vertex normals, so the mesh reader can use normal information</span></div><div class="line">  <span class="comment">// if available</span></div><div class="line">  mesh.request_vertex_normals();</div><div class="line"></div><div class="line">  <span class="comment">// assure we have vertex normals</span></div><div class="line">  <span class="keywordflow">if</span> (!mesh.has_vertex_normals())</div><div class="line">  {</div><div class="line">    std::cerr &lt;&lt; <span class="stringliteral">&quot;ERROR: Standard vertex property &#39;Normals&#39; not available!\n&quot;</span>;</div><div class="line">    <span class="keywordflow">return</span> 1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <a class="code" href="a02029.html">OpenMesh::IO::Options</a> opt;</div><div class="line">  <span class="keywordflow">if</span> ( ! <a class="code" href="a01236.html#ac417960ec28ffdd7e7003a2b1ebb2d1c">OpenMesh::IO::read_mesh</a>(mesh,argv[1], opt))</div><div class="line">  {</div><div class="line">    std::cerr &lt;&lt; <span class="stringliteral">&quot;Error loading mesh from file &quot;</span> &lt;&lt; argv[1] &lt;&lt; std::endl;</div><div class="line">    <span class="keywordflow">return</span> 1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// If the file did not provide vertex normals, then calculate them</span></div><div class="line">  <span class="keywordflow">if</span> ( !opt.check( <a class="code" href="a02029.html#a9f4f797b08c045b611eaa6f8d149da21ad989c6d671050e12953b648c4c72dded">OpenMesh::IO::Options::VertexNormal</a> ) )</div><div class="line">  {</div><div class="line">    <span class="comment">// we need face normals to update the vertex normals</span></div><div class="line">    mesh.request_face_normals();</div><div class="line"></div><div class="line">    <span class="comment">// let the mesh update the normals</span></div><div class="line">    mesh.<a class="code" href="a02389.html#a601f21014e50bd5a2243b0e4849c9c14">update_normals</a>();</div><div class="line"></div><div class="line">    <span class="comment">// dispose the face normals, as we don&#39;t need them anymore</span></div><div class="line">    mesh.release_face_normals();</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// move all vertices one unit length along it&#39;s normal direction</span></div><div class="line">  <span class="keywordflow">for</span> (MyMesh::VertexIter v_it = mesh.vertices_begin();</div><div class="line">       v_it != mesh.vertices_end(); ++v_it)</div><div class="line">  {</div><div class="line">    std::cout &lt;&lt; <span class="stringliteral">&quot;Vertex #&quot;</span> &lt;&lt; *v_it &lt;&lt; <span class="stringliteral">&quot;: &quot;</span> &lt;&lt; mesh.point( *v_it );</div><div class="line">    mesh.set_point( *v_it, mesh.point(*v_it)+mesh.normal(*v_it) );</div><div class="line">    std::cout &lt;&lt; <span class="stringliteral">&quot; moved to &quot;</span> &lt;&lt; mesh.point( *v_it ) &lt;&lt; std::endl;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// don&#39;t need the normals anymore? Remove them!</span></div><div class="line">  mesh.release_vertex_normals();</div><div class="line"></div><div class="line">  <span class="comment">// just check if it really works</span></div><div class="line">  <span class="keywordflow">if</span> (mesh.has_vertex_normals())</div><div class="line">  {</div><div class="line">    std::cerr &lt;&lt; <span class="stringliteral">&quot;Ouch! ERROR! Shouldn&#39;t have any vertex normals anymore!\n&quot;</span>;</div><div class="line">    <span class="keywordflow">return</span> 1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordflow">return</span> 0;</div><div class="line">}</div></div><!-- fragment --> </div></div><!-- contents -->
</div><!-- doc-content -->
<hr>
<address>
<small>
<a href="http://www.rwth-graphics.de" style="text-decoration:none;">
</a>
Project <b>OpenMesh</b>, 
&copy;&nbsp; Computer Graphics Group, RWTH Aachen.
Documentation generated using 
<a class="el" href="http://www.doxygen.org/index.html">
<b>doxygen</b>
</a>.
</small>
</address>
</body>
</html>
